package com.whl215.kit.adapter

import com.whl215.kit.adapter.wrap.GrapeNodeWrapper


/**
 * author： happiness
 * date： 2021/2/24
 * description：基于多类型实现的 分组adapter
 * 还有有个问题呀 因为实现机制的原因   wrapper 即使 adapter 也是 bean
 * 这就导致了 在嵌套数据时 必须把原始数据 和 wrapper 进行某种方式的转换  要么 数据直接继承 wrapper 要么 遍历组装数据
 * 感觉都不太优雅呀 但又是不可避免的  又不想使用 class注册的方式 zzz 难了
 *
 */
class GrapeNodeAdapter : GrapeBaseMultiAdapter<GrapeNodeWrapper>() {

    override fun setData(list: List<GrapeNodeWrapper>) {
        super.setData(flatData("", list))
    }

    /**
     * 扁平化数据
     */
    private fun flatData(parentId: String, list: List<GrapeNodeWrapper>): List<GrapeNodeWrapper> {
        val nodeList = mutableListOf<GrapeNodeWrapper>()
        for (item in list) {
            item.groupId = parentId
            nodeList.add(item)
            if (item.isExpend && item.getChildren().isNotEmpty()) {
                nodeList.addAll(flatData(item.getItemId(), item.getChildren()))
            }
        }
        return nodeList

    }
    /**
     * 扁平化数据
     */
    private fun flatData(parentId: String, item: GrapeNodeWrapper): List<GrapeNodeWrapper> {
        val nodeList = mutableListOf<GrapeNodeWrapper>()
        item.groupId = parentId
        nodeList.add(item)
        if (item.isExpend && item.getChildren().isNotEmpty()) {
            nodeList.addAll(flatData(item.getItemId(), item.getChildren()))
        }
        return nodeList

    }


    /**
     * 展开某一组
     */
    fun expend(position: Int) {
        val item = getItem(position)
        if (!item.isExpend) {
            item.isExpend = true
            if (item.getChildren().isNotEmpty()) {
                val list = flatData(item.getItemId(), item.getChildren())
                addData(position + 1, list)
            }
        }
    }

    /**
     * 折叠某一组
     */
    fun collapse(position: Int) {
        val item = getItem(position)
        if (item.isExpend) {
            item.isExpend = false
            if (item.getChildren().isNotEmpty()) {
                val list = flatData(item.getItemId(), item.getChildren())
                removeAll(position + 1, list)
            }
        }

    }

    /**
     * 需要删除 plainList中展示的数据  调用super.removeAt(index)即可
     * 需要删除 parent.children.removeAt(index) 不然下次折叠展开之后 数据仍然会展示出来
     */
    override fun removeAt(index: Int) {
        val element = mList[index]
        if (element.groupId.isNotEmpty()){
            for (item in mList) {
                if (item.getItemId() == element.groupId) {
                    if (item.getChildren().isNotEmpty()) {
                        item.removeChild(element)
                    }
                    break
                }
            }
        }

        collapse(index)
        super.removeAt(index)
    }

    override fun remove(element: GrapeNodeWrapper) {
        if (element.groupId.isNotEmpty()){
            for (item in mList) {
                if (item.getItemId() == element.groupId) {
                    if (item.getChildren().isNotEmpty()) {
                        item.removeChild(element)
                    }
                    break
                }
            }
        }
        super.remove(element)
    }

    /**
     * 添加一条数据
     * @param parentIndex ==-1 即默认值 调用时 adapter.addData(HLNodeWrapper) 表示 添加到数据数据末尾 表示添加一条组数据
     *              >=0 例如 adapter.addData(0,HLNodeWrapper) 为 下标为0的分组 添加一条子项数据 到末尾
     */
    fun addNode(parentIndex: Int = -1, item: GrapeNodeWrapper) {
        var insertIndex = -1
        var itemCount = -1

        if (parentIndex >= 0) {
            val wrapper = mList[parentIndex]
            wrapper.addChild(item)
            val childList = flatData(wrapper.getItemId(), wrapper)
            val addList = flatData(wrapper.getItemId(), item)
            insertIndex = parentIndex + childList.size-1
            itemCount = 1
            if (wrapper.isExpend){
                mList.addAll(insertIndex, addList)
                notifyItemRangeChanged(insertIndex,itemCount)
            }
        } else {
            val addList = flatData("", item)
            insertIndex = mList.size
            itemCount = addList.size
            mList.addAll(addList)
            notifyItemRangeChanged(insertIndex,itemCount)
        }


    }

    /**
     * 添加一条分组数据
     * @param index ==-1 即默认值 调用时 adapter.addData(HLNodeWrapper) 表示 添加到数据数据末尾 表示添加一条组数据
     *              >=0 例如 adapter.addData(0,HLNodeWrapper) 为 下标为0的分组 添加一条子项数据 到末尾
     */
    fun addNode(parentIndex: Int = -1, list: List<GrapeNodeWrapper>) {
        var insertIndex = -1
        var itemCount = -1
        if (parentIndex >= 0) {
            val wrapper = mList[parentIndex]
            if (wrapper.isExpend) {
                //如果当前分组是展开的 则从展开分组的最后一个子项的位置开始添加
                insertIndex = parentIndex + flatData(wrapper.getItemId(), wrapper.getChildren()).size+1
                //展开要添加的数据集合
                val realList = flatData(wrapper.getItemId(),list)
                itemCount = realList.size
                //添加要展示的数据
                mList.addAll(insertIndex, realList)
            }
            for (item in list) wrapper.addChild(item)

        } else {
            insertIndex = mList.size
            val realList = flatData("",list)
            itemCount = realList.size
            mList.addAll(realList)
        }
        notifyItemRangeInserted(insertIndex, itemCount)
    }


    /**
     * 需要动态的添加删除修改数据
     * 分组列表 分成两部分 1.有增删操作的 2. 没有增删操作
     * 没有增删操作 就正常展示即可 setData() expend() collapse()
     * 有增删改操作. 当分组数据添加到recyclerView中. 此时数据是分成两部分的 比如分组1的三个子项 被添加adapter持有的list
     * 此时三个子项 即存在于adapter.list   又存在group.children 两份数据.
     * 仅仅是展示 两份数据也不会有啥问题.  如果涉及到增删改 两份数据就有问题了.
     * 比如 在itemClick事件 通过position修改了当前数据项的 修改的数据是adapter.list中的数据 对应的group.children中的数据并没有修改
     * 展开,收起数据是通过 group.children的增加删除操作 所以有一个数据同步问题
     *
     * 那么问题来了
     * 数据扁平 打破分组的层级结构之后 如何区分 谁是header 谁是content呢 甚至三层嵌套呢 .假设如果是三层嵌套
     * 怎么准确找到其中的一项数据呢 做增删改的操作
     * 展开收起操作怎么搞
     * 1.展开收起
     *    重写点击事件. 检查类型
     *      if viewType == R.layout.header
     *          if wrapper.isExpend  adapter.collapse()  else adapter.expend()
     *          展开收起操作的同时 也可以添加点别的逻辑操作 虽然不常用
     *      else if viewType == R.layout header2
     *          if wrapper.isExpend  adapter.collapse()  else adapter.expend()
     *      else if viewType == R.layout.content
     *          业务操作
     * 2.增删改
     *      如何解决 修改数据 adapter.list  和  group.children 数据同步的问题.
     *      关键在于 扁平列表中 找到child对应的 group. 二级找到一级  一级group
     *      突然发现 存储下标在数据里 万一增删数据 集合位置变了 真实的位置 于对象中存储的业务下遍字段对不上 就完犊子
     *      所以不能存储到数据里
     */

}